home *** CD-ROM | disk | FTP | other *** search
- /* f r e a d
- *
- * Read a series of records from an input stream. The function
- * returns the number of items (not bytes) read. The function
- * stops reading when the number of items is satisfied or when
- * EOF is encountered.
- *
- * Patchlevel 1.1
- *
- * Edit History:
- * 05-Sep-1989 Include limits.h if INT_MAX undefined so removing
- * need to define MINIX when compiling. Fix void *
- * problems by assigning to an unsigned char *.
- * Add EINTR repeat code after read().
- * 04-Sep-1989 Add code for reading very large objects.
- * 01-Sep-1989 Use Henry Spencer's ideas to speed up code by reading
- * directly into buffer.
- */
-
- #include "stdiolib.h"
-
- #if defined(BSD)
- # include <values.h>
- # define INT_MAX (MAXINT)
- #endif
-
- #if !defined(INT_MAX)
- # include <limits.h>
- #endif
-
- /*LINTLIBRARY*/
-
- int fread(ptr, size, nitems, fp)
-
- void *ptr; /* buffer */
- unsigned size; /* size of record */
- unsigned nitems; /* number of items */
- FILE *fp; /* stream */
-
- {
- int red; /* bytes read in read call */
- int read(); /* read call */
- unsigned char *p; /* buffer pointer */
-
- /* Phase 1 --- Amount to read overflows INT_MAX */
- unsigned int burstsize; /* size aligned chunk to read */
- unsigned int itemsperburst; /* items read per burst */
- unsigned int itemsleft; /* items left */
- unsigned int copyitems; /* items to copy */
-
- /* Phase 2 --- Write remainder */
- unsigned int bytestotal; /* total number of bytes */
- unsigned int bytesleft; /* total number of bytes left */
- unsigned int copybytes; /* bytes to copy directly to buffer */
- unsigned char *q; /* pointer into getc buffer */
-
- /* Items left to read */
- if ((itemsleft = nitems) == 0 || size == 0)
- return 0;
-
- /* Flush stdout */
- if (fp == stdin && TESTFLAG(stdout, _IOLBF))
- (void) fflush(stdout);
-
- /* Fix void * casting problems */
- p = (unsigned char *) ptr;
-
- /* Read very large objects */
- if ((itemsperburst = INT_MAX / size) == 0) {
- do {
- bytesleft = size;
- do {
- if ((burstsize = BYTESINREADBUFFER(fp)) != 0) {
- if (burstsize > bytesleft)
- burstsize = bytesleft;
- q = GETREADPTR(fp);
- UNROLL_DO(freadlarge, burstsize, *p++ = *q++);
- SETREADPTR(fp, q);
- }
- else {
- if ((burstsize = INT_MAX) > bytesleft)
- burstsize = bytesleft;
- do
- red = read(fileno(fp), (char *) p, (int) burstsize);
- while (red == -1 && errno == EINTR);
- if (red != burstsize)
- return (nitems-itemsleft);
- p += burstsize;
- }
- } while ((bytesleft -= burstsize) != 0);
- } while (--itemsleft);
- return nitems;
- }
-
- /* Read large amounts of data first */
- for (burstsize = itemsperburst * size; itemsleft > itemsperburst; ) {
- if (itemsleft == nitems &&
- (copybytes = BYTESINREADBUFFER(fp)) != 0) {
- copyitems = copybytes/size;
- if (copyitems > itemsleft)
- copybytes = (copyitems = itemsleft) * size;
- itemsleft -= copyitems;
- if ((bytesleft = copybytes%size) != 0)
- bytesleft = size-bytesleft;
- q = GETREADPTR(fp);
- UNROLL_DO(freadburst, copybytes, *p++ = *q++);
- SETREADPTR(fp, q);
- if (bytesleft != 0) {
- do
- red = read(fileno(fp), (char *) p, (int) bytesleft);
- while (red == -1 && errno == EINTR);
- if (red != bytesleft)
- return (nitems-itemsleft);
- itemsleft--;
- }
- }
- else {
- do
- red = read(fileno(fp), (char *) p, (int) burstsize);
- while (red == -1 && errno == EINTR);
- if (red != burstsize) {
- if (red == -1)
- red = 0;
- return (nitems-itemsleft) + (red/size);
- }
- p += burstsize;
- itemsleft -= itemsperburst;
- }
- }
-
- /* At this point itemsleft contains the number of items left to
- * read. The read buffer may not be empty. itemsleft*size
- * will not overflow INT_MAX.
- */
-
- if ((bytesleft = bytestotal = size*itemsleft) != 0) {
-
- /* Partially filled read buffer */
- if ((copybytes = BYTESINREADBUFFER(fp)) != 0) {
- if (copybytes > bytesleft)
- copybytes = bytesleft;
- bytesleft -= copybytes;
- q = GETREADPTR(fp);
- UNROLL_DO(freadbytes, copybytes, *p++ = *q++);
- SETREADPTR(fp, q);
- }
-
- /* Read rest of object directly to user buffer */
- if (bytesleft != 0) {
- do
- red = read(fileno(fp), (char *) p, (int) bytesleft);
- while (red == -1 && errno == EINTR);
- if (red != -1)
- bytesleft -= red;
- }
- }
-
- return (nitems-itemsleft) + (bytestotal-bytesleft)/size;
- }
-